<?php

namespace App\Repositories;

use Storage;
use App\Models\Picture;
use App\Models\PictureMapping;

class PictureRepository
{
    public function __construct(){}

    // overwrite_path_by_object根据$object_type, $object_id去覆盖文件且更新file表
    public function upload($fileCharater, $objectType = '', $objectId = 0, $subObjectKey = null)
    {
        $userLogin = login_user();
        // 括号里面的是必须加的哦 如果括号里面的不加上的话，下面的方法也无法调用的
        if (!$fileCharater->isValid()) {
            return false;
        }

        $path = $fileCharater->getRealPath();

        $originName = $fileCharater->getClientOriginalName();
        //七牛
        $driver = Storage::getDefaultDriver();

        $file['md5'] = md5_file($path);
        $file['sha1'] = sha1_file($path);
        $file['name'] = $originName;
        $file['size'] = $fileCharater->getClientSize();
        $file['mimetype'] = $fileCharater->getClientMimeType();
        $file['ext'] = $fileCharater->getClientOriginalExtension();
        $file['location'] = $driver;
        $ff = File::query()->where('md5', $file['md5'])->first();

        if (!$ff) {
            switch ($driver) {
                case 'qiniu':
                    $res = $this->uploadToQiniu($fileCharater);
                    break;
                case 'azure':
                    $res = $this->uploadToAzure($fileCharater);
                    break;
                case 's3':
                    $res = $this->uploadToOss($fileCharater);
                    break;
                case 'local':
                case 'public':
                default:
                    $res = $this->uploadToLocal($fileCharater);
                    break;
            }
        }

        if (!$ff && !$res['success']) {
            return false;
        }
        if (!$ff) {
            $file['created_at'] = date('Y-m-d H:i:s');
            $file['source'] = '';
            $file['create_user_id'] = $userLogin['id'];
            $file['create_user_name'] = $userLogin['username'];
            $file['path'] = $res['path'];
            $file_id = File::query()->insertGetId($file);
        } else {
            $file_id = $ff['id'];
            if ($ff['deleted_at']) {
                File::withTrashed()->where('id', $file_id)->update(['deleted_at' => null]);
            }
            if ($ff['name'] !== $originName) {
                // 同样的文件，文件名不一样，更新成新名字
                File::query()->where('id', $file_id)->update(['name' => $originName]);
            }
        }

        if (!$file_id) {
            throw new \Exception('文件上传失败');
        }

        // 不写入mapping，直接返回
        if (!$objectId || !$objectType) {
            $res = File::query()->find($file_id)->toArray();
            $res['full_path'] = image_path($res['path']);

            return $res;
        }

        // 写入mapping
        $map['file_id'] = $file_id;
        $map['object_type'] = $objectType;
        $map['object_id'] = $objectId;
        $map['sub_object_key'] = $subObjectKey;
        $map['created_at'] = date('Y-m-d H:i:s');

        $mapping = FileMapping::query()
            ->where('file_id', $file_id)
            ->where('object_type', $objectType)
            ->where('object_id', $objectId)
            ->where('sub_object_key', $subObjectKey)
            ->first();

        if ($mapping) {
            $mapId = $mapping->id;
        } else {
            $mapId = FileMapping::query()->insertGetId($map);
        }

        return $this->getFileByMapId($mapId);
    }

    public function getFileByMapId($mapId)
    {
        if (!$mapId) {
            return;
        }

        $res = FileMapping::query()
            ->select("file.*", "file_mapping.*")
            ->join('file', 'file_mapping.file_id','=', 'file.id' )
            ->where('file_mapping.id' , $mapId)
            ->first()
            ->toArray();

        $res['full_path'] = image_path($res['path']);

        return $res;
    }

    public function getFileById($fileId)
    {
        return File::query()->where('id', $fileId)->first();
    }

    public function uploadToLocal($fileCharater)
    {
        //获取文件的扩展名
        $ext = $fileCharater->getClientOriginalExtension();

        //获取文件的临时绝对路径
        $path = $fileCharater->getRealPath();

        // 按日期创建文件夹 定义文件名
        $filename = '/uploads/'  . date('Y-m-d') . '/' . uniqid() . '.' . $ext;

        //存储文件。disk里面的public。总的来说，就是调用disk模块里的public配置
        $res = Storage::disk('public')->put($filename, file_get_contents($path));

        if ($res) {
            return ['success' => true, 'path' => $filename];
        } else {
            return ['success' => false, 'msg' => '上传失败'];
        }
    }

    public function uploadToQiniu($fileCharater)
    {
        $ext = $fileCharater->getClientOriginalExtension();

        //获取文件的临时绝对路径
        $path = $fileCharater->getRealPath();

        // 按文件md5 定义文件名
        $disk = Storage::disk('qiniu');

        $md5 = md5_file($path);

        $filename = config('filesystems.disks.qiniu.file_dir') . $md5 . '.' . $ext;

        $res = $disk->put($filename, file_get_contents($path));

        if ($res) {
            return ['success' => true, 'path' => $filename];
        } else {
            return ['success' => false, 'msg' => '上传失败'];
        }
    }

    public function uploadToAzure($fileCharater)
    {
        $ext = $fileCharater->getClientOriginalExtension();

        //获取文件的临时绝对路径
        $path = $fileCharater->getRealPath();

        $md5 = md5_file($path);

        $filename = config('filesystems.disks.azure.file_dir') .'/'. date('Ym') .'/'. $md5 . '.' . $ext;

        $res = app(MicrosoftBlobRepository::class)->upload($path, $filename);

        $filename = '/' . config('filesystems.disks.azure.container_name') . '/' . $filename;

        if ($res) {
            return ['success' => true, 'path' => $filename];
        } else {
            return ['success' => false, 'msg' => '上传失败'];
        }
    }

    public function uploadToOss($fileCharater)
    {
        // @todo
    }

    public function removeMapFile(int $mid)
    {
        return FileMapping::query()->where(['id'=>$mid])->delete();
    }

    public function updateMapping(int $object_id, int  $object_type=1, array $file_ids = [])
    {
        FileMapping::where([
            'object_id' => $object_id,
            "object_type" => FileMapping::getObjectType($object_type)
        ])->delete();

        foreach ($file_ids as $k => $v) {
            FileMapping::create([
                'file_id'   => $v,
                'object_id' => $object_id,
                'object_type' => FileMapping::getObjectType($object_type)
            ]);
        }
    }

    /**
     * 文件列表(搜索)
     * @param  [type] $request [description]
     * @return [type]          [description]
     */
    public function getFileBySearch($request)
    {
        return FileMapping::select([
                'file_mapping.*',
                'file.name',
                'file.path',
                'file.ext',
                'file.mimetype',
                'file.size',
            ])
            ->leftJoin('file', 'file_mapping.file_id', '=', 'file.id')
            ->where(function ($query) use ($request) {
                $query->when(isset($request['object_type']) && !empty($request['object_type']), function ($query) use ($request) {
                    return $query->where('file_mapping.object_type', $request['object_type']);
                })
                ->when(isset($request['object_id']) && !empty($request['object_id']), function ($query) use ($request) {
                    if(is_array($request['object_id'])) {
                        return $query->whereIn('file_mapping.object_id', $request['object_id']);
                    }else{
                        return $query->where('file_mapping.object_id', intval($request['object_id']));
                    }
                });
            })->orderBy('file_mapping.id', 'desc')->paginate(15);
    }

}
